﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace msilgc.cbuilder.MSILSyntaxTree
{
    public interface IBasicBlock
    {
        
    }

    internal class BasicBlock : IBasicBlock {
        public readonly List<Instruction> Instructions;
        public readonly List<BasicBlock> Targets;
        public Instruction BranchInstruction;

        public BasicBlock(IEnumerable<Instruction> instructions) {
            Targets = new List<BasicBlock>();
            Instructions = new List<Instruction>(instructions);
        }

        public bool IsNormal { get { return !(IsFinally || IsExceptionHandler); } }
        public bool IsFinally;
        public bool IsExceptionHandler;
        public Type ExceptionTypeIfExceptionHandler;

        public IEnumerable<BasicBlock> TargetsThatAreNotTheNextBlock {
            get {
                if (Targets.Count > 1) {
                    var last = BranchInstruction ?? Instructions.Last();
                    var nextOffset = last.Offset + last.Inst.Size;
                    return Targets.Where(target => target.Offset != nextOffset);
                }
                if (Targets.Count == 1) {
                    return Targets;
                }
                return new BasicBlock[0];
            }
        } 

        public int Offset {
            get { return Instructions.Count > 0 ? Instructions[0].Offset : BranchInstruction.Offset; }
        }

        public int Length {
            get {
                var bodySize = 0;
                if (Instructions.Count > 0) {
                    var first = Instructions.First();
                    var last = BranchInstruction ?? Instructions.Last();
                    bodySize = last.Offset - first.Offset;
                }
                return bodySize + BranchInstruction.Inst.Size;
            }
        }
    }
}